#ifndef __PROCESS_POOL_H__
#define __PROCESS_POOL_H__

#include "Task.hpp"
#include <iostream>
#include <unistd.h>
#include <functional>
#include <string>
#include <sys/wait.h>
#include <sys/types.h>
#include <vector>
#include <cstdlib>
#include <ctime>

using callback_t = std::function<void(int fd)>;
#define NUM 5

class Channel
{
public:
    Channel()
    {
    }
    Channel(int fd, std::string name, pid_t id)
        : _wfd(fd), _name(name), _sub_target(id)
    {
    }
    ~Channel()
    {
    }
    int Getfd()
    {
        return _wfd;
    }
    std::string Getname()
    {
        return _name;
    }
    pid_t Getsub_target()
    {
        return _sub_target;
    }

private:
    int _wfd;
    std::string _name;
    pid_t _sub_target; // 目标子进程的id
};

class ProcessPool
{
public:
    ProcessPool(int num = NUM)
        : _num(num)
    {
        srand(time(nullptr));
    }
    ~ProcessPool()
    {
    }

    bool InitProcessPool(callback_t cb)
    {
        for (int i = 0; i < NUM; i++)
        {
            int pipefd[2] = {0};
            int n = pipe(pipefd);
            if (n < 0)
            {
                return false;
            }

            pid_t id = fork();
            if (id < 0)
            {
                return false;
            }
            if (id == 0)
            {
                close(pipefd[1]);
                //子进程会把之前父进程的所有写端也继承过来，也就是说子进程继承了向所有历史管道写入的权限（也就是继承了写端管道的fd）
                //所以我们要关掉所有历史的写端，fork之后父进程再向_channels插入新的管道不会影响子进程，发生写时拷贝，同时子进程改变_channels也不会影响父进程
                for(auto& ch : _channels)
                {
                    close(ch.Getfd());
                }
                // 子进程工作
                cb(pipefd[0]);
                exit(0);
            }
            close(pipefd[0]);
            std::string name = "Channel--" + std::to_string(i);
            std::cout << name << "被创建" << std::endl;
            _channels.emplace_back(pipefd[1], name, id);
            sleep(2);
        }
        return true;
    }

    void PollingCtrlSubProcess(int count)
    {
        if (count < 0)
            return;
        int index = 0;
        while (count--)
        {
            int who = index;
            index++;
            index %= _channels.size();
            int x = rand() % tasks.size();
            std::cout << "选择信道：" << _channels[who].Getname() << ",_channels[who].Getsub_target()" << std::endl;
            ssize_t n = write(_channels[who].Getfd(), &x, sizeof(x));
            if (n < 0)
            {
                std::cerr << "write error" << std::endl;
            }
            sleep(1); 
        }
    }

    void WaitSubProcess()
    {
        // for(auto& ch : _channels)
        // {
        //     close(ch.Getfd());
        // }
        // for(auto& ch : _channels)
        // {
        //     pid_t id = waitpid(ch.Getsub_target(), nullptr, 0);
        //     if(id == -1)
        //     {
        //         std::cerr << "waitpid error" << std::endl;
        //     }
        // }
        for(auto& ch: _channels)
        {
            close(ch.Getfd());
            pid_t id = waitpid(ch.Getsub_target(), nullptr, 0);
            if(id == -1)
            {
                std::cerr << "waitpid error" << std::endl;
            }
        }
    }

private:
    std::vector<Channel> _channels;
    int _num; // 创建几个子进程
};

#endif